package org.dut.community.util;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class SensitiveFilter {
    // 替换符
    private static final String REPLACEMENT = "***";

    private class TrieNode {
        // 关键词结束标识
        private boolean isKeyWordEnd = false;
        // 子节点
        private Map<Character,TrieNode> subNodes = new HashMap<>();

        public boolean isKeyWordEnd() {
            return isKeyWordEnd;
        }
        public void setKeyWordEnd(boolean keyWordEnd) {
            isKeyWordEnd = keyWordEnd;
        }

        public void addSubNode(Character c, TrieNode node) {
            subNodes.put(c,node);
        }

        public TrieNode getSubNode(Character c) {
            return subNodes.get(c);
        }
    }

    // 根节点
    private TrieNode rootNode = new TrieNode();

    // 初始化敏感词库,服务器启动时自动初始化
    @PostConstruct
    public void init(){
        try(InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");
            BufferedReader reader = new BufferedReader(new InputStreamReader(is)))  {
            String keyWord;
            while((keyWord = reader.readLine()) != null){
                this.addKeyWord(keyWord);
            }
        } catch (IOException e) {
            log.error("加载敏感词文件失败："+e.getMessage());
        }
    }

    // 添加单个敏感词
    private void addKeyWord(String keyWord) {
        TrieNode node = rootNode;
        for (int i = 0; i < keyWord.length(); i++) {
            Character c = keyWord.charAt(i);
            TrieNode subNode = node.getSubNode(c);
            if (subNode == null) {
                subNode = new TrieNode();
                node.addSubNode(c,subNode);
            }
            node = subNode;
        }
        node.setKeyWordEnd(true);
    }

    // 判断符号，符号直接跳过
    private boolean isSymbol(Character c){
        return !CharUtils.isAsciiAlphanumeric(c)
                && (c < 0x2E80 || c > 0x9FFF); // 东亚字符(中、日、韩)
    }

    // 过滤敏感词
    public String filter(String text){
        if(StringUtils.isBlank(text)){
            return null;
        }

        TrieNode tmp1 = rootNode;
        int tmp2 = 0;
        int tmp3 = 0;
        StringBuilder res = new StringBuilder();

        while(tmp3 < text.length()){
            char c = text.charAt(tmp3);
            if(isSymbol(c)){
                if(tmp1 == rootNode){
                    res.append(c);
                    tmp2++;
                }
                tmp3++;
            }else{
                tmp1 = tmp1.getSubNode(c);
                if(tmp1 == null){
                    res.append(text.charAt(tmp2));
                    tmp2++;
                    tmp3 = tmp2;
                    tmp1 = rootNode;
                }else if(tmp1.isKeyWordEnd()){
                    res.append(REPLACEMENT);
                    tmp3++;
                    tmp2 = tmp3;
                    tmp1 = rootNode;
                }else{
                    tmp3++;
                }
            }
        }
        // 针对第三种情况，子字符串是敏感词的前缀
        res.append(text.substring(tmp2));
        return res.toString();
    }

}
